package com.joysuch.wwyt.datasync.service.impl;

import com.joysuch.wwyt.bp.entity.BpDeviceFacilityStopRecoverRecord;
import com.joysuch.wwyt.bp.entity.BpMainMaterial;
import com.joysuch.wwyt.bp.entity.investigate.BpInvestigatePlan;
import com.joysuch.wwyt.bp.entity.investigate.BpInvestigateRecord;
import com.joysuch.wwyt.bp.entity.investigate.BpInvestigateTask;
import com.joysuch.wwyt.bp.repository.BpInvestigatePlanRepository;
import com.joysuch.wwyt.bp.repository.BpInvestigateRecordRepository;
import com.joysuch.wwyt.bp.repository.BpInvestigateTaskDao;
import com.joysuch.wwyt.datasync.DataSyncType;
import com.joysuch.wwyt.datasync.entity.DataSyncInfo;
import com.joysuch.wwyt.datasync.repository.DataSyncInfoDao;
import com.joysuch.wwyt.datasync.service.DataSyncRegister;
import com.joysuch.wwyt.datasync.support.AopDataSyncDaoInterceptor;
import com.joysuch.wwyt.workflow.entity.WorkFlowProcess;
import com.joysuch.wwyt.workflow.entity.WorkFlowTask;
import com.joysuch.wwyt.workflow.repository.WorkFlowProcessDao;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.joysuch.wwyt.datasync.service.DataSyncRegister.loadFromJson;

/**
 * 只处理工作流中的隐患管理任务，其他工作流任务不同步
 */
@Component
@Slf4j
@ConditionalOnProperty(value = "wwyt.feature.datasync.customer", havingValue = "xinyuan")
public class XinyuanDataSyncCondition extends  BaseDataSyncCondition{

    @Resource
    @Lazy
    private WorkFlowProcessDao workFlowProcessDao;
    @Resource
    @Lazy
    private BpInvestigatePlanRepository bpInvestigatePlanDao;
    @Resource
    @Lazy
    private DataSyncInfoDao dataSyncInfoDao;
    @Resource
    @Lazy
    private BpInvestigateTaskDao bpInvestigateTaskDao;
    @Resource
    @Lazy
    private BpInvestigateRecordRepository bpInvestigateRecordRepository;


    @PostConstruct
    public void loadRegisterInfo() {
        try {
            loadFromJson(this.getClass().getClassLoader().getResourceAsStream("datasync-register-xinyuan.json"));
        } catch(Exception e) {
            throw new RuntimeException("加载新远配置文件错误", e);
        }
    }

    @Override
    public AopDataSyncDaoInterceptor.Info extractSyncInfo(MethodInvocation invocation) {
        if(invocation.getMethod().getName().startsWith("find") || invocation.getMethod().getName().startsWith("select")) {
            return null;
        }
        AopDataSyncDaoInterceptor.Info info = parseBasicInfo(invocation);
        if(info != null && info.getDomainClass() == WorkFlowTask.class) {
            // 只传输工作流中的隐患管理部分
            Object[] arguments = info.getInvocation().getArguments();
            if (arguments == null || arguments.length == 0) {
                return null;
            }
            for (Object arg : arguments) {
                if (arg instanceof Iterable) {
                    Iterable it = (Iterable) arg;
                    for (Object obj : it) {
                        if(isDangerInfoWorkflow((WorkFlowTask) obj)) {
                            return info;
                        }
                    }
                } else {
                    if(isDangerInfoWorkflow((WorkFlowTask) arg)) {
                        return info;
                    }
                }
            }
            return null;
        } else if(info != null && info.getDomainClass() == BpInvestigateTask.class) {
            // 隐患排查任务，向上寻找隐患排查计划并写入变更表
            // 隐患排查任务ID列表
            List<Long> ids = findEntityIds(info);
            if(!ids.isEmpty()) {
                log.debug("有隐患排查任务变更: {}", ids);
                List<Long> planIds = bpInvestigateTaskDao.findPlanIdByIdIn(ids);
                log.debug("隐患排查任务关联的排查计划: {}", planIds);
                createDataChangeInfos(planIds, DataSyncType.UPDATE);
            }
        } else if(info != null && info.getDomainClass() == BpInvestigateRecord.class) {
            // 隐患排查记录, 向上寻找隐患排查计划并写入变更表
            // 隐患排查记录ID
            List<Long> ids = findEntityIds(info);
            if(!ids.isEmpty()) {
                log.debug("有隐患排查记录变更: {}", ids);
                List<Long> planIds = bpInvestigateRecordRepository.findPlanIdByIdIn(ids);
                log.debug("隐患排查记录关联的排查计划: {}", planIds);
                createDataChangeInfos(planIds, DataSyncType.UPDATE);
            }
        }
        return info;
    }

    private void createDataChangeInfos(List<Long> planIds, DataSyncType update) {
        for(Long id: planIds) {
            DataSyncInfo data = new DataSyncInfo();
            data.setChangeType(update.getCode());
            // 暂不保存数据，防止循环引用，导致栈溢出

            data.setDataId(id);
            data.setState((byte) 0);
            String serviceName = DataSyncRegister.get(BpInvestigatePlan.class);
            data.setTableName(serviceName);
            bpInvestigatePlanDao.findById(id).ifPresent(p -> {
                data.setTenentId(p.getTenentId());
                data.setOrgCode((p.getOrgCode()));
                dataSyncInfoDao.save(data);
            });
        }

    }

    private List<Long> findEntityIds(AopDataSyncDaoInterceptor.Info info) {
        Object[] arguments = info.getInvocation().getArguments();
        if (arguments == null || arguments.length == 0) {
            return Collections.EMPTY_LIST;
        }
        List<Long> list = new ArrayList<>(3);
        for (Object arg : arguments) {
            if (arg instanceof Iterable) {
                Iterable it = (Iterable) arg;
                for (Object obj : it) {
                    Long id = getIdFromArg(info, arg, info.getType() == DataSyncType.DELETE);
                    if(id != null) {
                        list.add(id);
                    }
                }
            } else {
                Long id = getIdFromArg(info, arg, info.getType() == DataSyncType.DELETE);
                if(id != null) {
                    list.add(id);
                }
            }
        }
        return list;
    }

    private Long getIdFromArg(AopDataSyncDaoInterceptor.Info info, Object arg, boolean isdelete) {
        if(isdelete && arg instanceof Long) {
            // 只有删除方法接受 ID参数
            return (Long)arg;
        } else if(info.getDomainClass().isAssignableFrom(arg.getClass())) {
            Object id = info.getEntityInformation().getId(arg);
            return (Long)id;
        }
        return null;
    }

    // 判断是否危险信息
    private boolean isDangerInfoWorkflow(WorkFlowTask task) {
        WorkFlowProcess process = workFlowProcessDao.findById(task.getProcessId()).orElse(null);
        if (process != null) {
            // if ("隐患管理".equals(process.getBizName())) {
            // logger.debug("隐患管理: {}" + task);
            // if ("隐患排查".equals(task.getRefSource())) {
            // return info.serviceName + ":" + process.getBizName() + ":" + task.getPreTaskName();
            // } else {

            return "隐患管理".equals(process.getBizName());
        }
        return false;
    }


}
